﻿#include "gamecontrol.h"
#include <QFile>
#include <QTextStream>
//#include "logger.h"
#include "readconfig.h"
#include <QDebug>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonParseError>
#include <QDateTime>
#include "currentuserdata.h"
#include <QTimer>
#include "dataFormate.h"
//LOG4QT_DECLARE_STATIC_LOGGER(logger, GameControl)

GameControl* GameControl::m_GameParamControl = NULL;

GameControl::GameControl(QWidget *parent)
    : QWidget(parent),
      m_gameSocket(NULL),
      m_waitingDialog(NULL),
      waitTimer(NULL),
      m_sendTimer(NULL),
      m_activeMaxAngle(0),
      m_activeMinAngle(0),
      m_maxAngle(0),
      currentXAngle(0),
      currentYAngle(0)
{
    m_Process = new QProcess();
    sender = new QUdpSocket(this);
    initGameSocket();
    m_waitingDialog = new WaitingDialog();
    m_waitingDialog->setWaitingType(INITWAITING);
    m_trainingReport = new TrainingReport;
    waitTimer = new QTimer();
    waitTimer->setInterval(5000);
    waitTimer->setSingleShot(true);
    connect(waitTimer,SIGNAL(timeout()),this,SLOT(slotWaitTimer()));


    m_sendTimer = new QTimer();
    m_sendTimer->setInterval(5000);
//    connect(m_sendTimer,SIGNAL(timeout()),this,SLOT(slotSendRealParam()));

}

void GameControl::initGameSocket()
{
    m_gameSocket = new QUdpSocket();
    int16_t port;
    QString IP;
    ReadConfig::getInstance()->getGameSeverAddress(port,IP);
    if(m_gameSocket->bind(12000))
    {
        qDebug()<<(QString("游戏服务端口%1").arg(port));
    }
    connect(m_gameSocket,&QUdpSocket::readyRead,this,&GameControl::slotReceiveGameData);
}

GameControl* GameControl::getInstance()
{
    if(!m_GameParamControl)
    {
        m_GameParamControl = new GameControl();
    }
    return m_GameParamControl;
}

void GameControl::updateXml(ST_GameParam& st_GameParam)
{
    QFile file("./game/gameConfig.xml");
    if(!file.open(QFile::ReadOnly))
        return;
    QDomDocument doc;

    QString errMsg;
    if(!doc.setContent(&file,&errMsg))
    {
        file.close();
        return;
    }
    file.close();

    QDomElement root = doc.documentElement();

    if(1)
    {
        QDomNodeList timeList = root.elementsByTagName("GameTime");
        QDomNode timeNode = timeList.at(0);
        QDomNode oldnode=timeNode.firstChild();
        timeNode.firstChild().setNodeValue(QString::number(st_GameParam.gameTime*60));
        QDomNode newNode = timeNode.firstChild();
        timeNode.replaceChild(newNode,oldnode);
    }

    if(!file.open(QFile::WriteOnly|QFile::Truncate))
        return;
    //输出到文件
    QTextStream out_stream(&file);
    doc.save(out_stream,4); //缩进4格
    file.close();

}

void GameControl::setGamParam(ST_GameParam& st_GameParam)
{
    m_st_gameParam = st_GameParam;

    m_maxAngle =st_GameParam.maxAngle;

    pointList.clear();
    updateXml(st_GameParam);
    startGame(st_GameParam.path);
    //打开游戏载入界面
    m_waitingDialog->setDialogCloseState(false);
    //填充训练报告参数
    ST_PatientMsg st_patientMsg = CurrentUserData::getInstace()->getCurrentPatientMsg();
    st_TrainReport.ID = st_patientMsg.ID;
    st_TrainReport.userName = st_patientMsg.userName;
    st_TrainReport.sex = st_patientMsg.sex;
    st_TrainReport.userPhone = st_patientMsg.userPhone;
    st_TrainReport.height = st_patientMsg.height;
    st_TrainReport.age = st_patientMsg.age;
    st_TrainReport.remark = st_patientMsg.remarkMessage;

    st_TrainReport.resistance = st_GameParam.resistance;
    st_TrainReport.range = st_GameParam.maxAngle;
    st_TrainReport.trainDifficulty = st_GameParam.trainDifficulty;
    st_TrainReport.gameplay = st_GameParam.gameplay;
    st_TrainReport.direction = st_GameParam.direction;
    st_TrainReport.reportDate = QDateTime::currentDateTime();
    st_TrainReport.game = st_GameParam.game;


}

QList<ST_GameMsg> GameControl::getGameMsgs()
{
    QList<ST_GameMsg> gameMsgList;
    QFile file("./ConfigFile/gameListConfig.xml");

    if(!file.open(QIODevice::ReadOnly))
    {
        qDebug()<<"read gameListConfig failed";
        return gameMsgList;
    }
    QDomDocument doc;
    QString error;
    int row,colum;
    if(!doc.setContent(&file,&error,&row,&colum))
    {
        file.close();
        return gameMsgList;
    }
    file.close();

    QDomElement root=doc.documentElement(); //返回根节点

    QDomNode node=root.firstChild(); //获得第一个子节点

    while(!node.isNull())
    {
        if(node.isElement()) //如果节点是元素
        {
            ST_GameMsg st_GameMsg;
            QDomElement e=node.toElement();
            st_GameMsg.gameID = e.attribute("ID").toInt();
            st_GameMsg.gameName = e.attribute("name");
            st_GameMsg.gamePath = e.attribute("path");
            st_GameMsg.iconPath = e.attribute("iconPath");
            QString suitType = e.attribute("suitType");
            gameMsgList.append(st_GameMsg);
            m_mapGameName.insert(st_GameMsg.gameName,st_GameMsg);
        }
        node = node.nextSibling();
    }
    return gameMsgList;
}

ST_GameMsg GameControl::getGameMsgByName(QString name)
{
    ST_GameMsg st_gameMsg;
    QMapIterator<QString, ST_GameMsg> i(m_mapGameName);

    while(i.hasNext())
    {
        i.next();
    }

    if(m_mapGameName.contains(name))
    {
        st_gameMsg = m_mapGameName.value(name);
    }
    return st_gameMsg;
}

void GameControl::startGame(QString path)
{
    //告知下位机开始游戏
    sendCmdToSlave(START_CMD_E);

    pointList.clear();
    //1.开启游戏进程
    if(path.isEmpty())
        return;
    QString hardDisk = path.mid(0,2);
    hardDisk.append("\n\r");

    QString gameName = path.mid(path.lastIndexOf('/')+1);
    gameName.prepend("start ");
    gameName.append("\n\r");
    QString gamePath = path.mid(0,path.lastIndexOf('/'));
    gamePath.prepend("cd ");
    gamePath.append("\n\r");
    m_Process->start("cmd.exe");
    //切换盘符
    m_Process->write(hardDisk.toLatin1());
    //进入文件夹
    m_Process->write(gamePath.toLatin1());
    //开启进程
    m_Process->write(gameName.toLatin1());
    m_Process->write("exit\n\r");
    m_Process->waitForFinished();
    m_Process->close();

}

//游戏数据接收
void GameControl::slotReceiveGameData()
{
    while(m_gameSocket->hasPendingDatagrams())
    {
        QByteArray buf;
        buf.resize(m_gameSocket->pendingDatagramSize());
        m_gameSocket->readDatagram(buf.data(),buf.size());
        parseGameMsg(buf);
    }

}

void GameControl::parseGameMsg(QByteArray jsonArray)
{
    QJsonParseError jsonError;
    QJsonDocument doucment = QJsonDocument::fromJson(jsonArray, &jsonError);  // 转化为 JSON 文档

    if (!doucment.isNull() && (jsonError.error == QJsonParseError::NoError))
    {
        if(doucment.isObject())
        {
            QJsonObject object = doucment.object();  // 转化为对象
            if(object.contains("msgID"))
            {
                int msgID = object.value("msgID").toInt();
                switch(msgID)
                {
                case 1: //游戏开始信号
                {   m_waitingDialog->setDialogCloseState(true);
                    m_spasmTimes = 0;
                    isTraining = true;
                    waitTimer->start();
                    pointList.clear();
                    emit signalGameState(e_TrainMode,GameStart_E);

                }
                    break;
                case 3: //结束信息
                {
                    isTraining = false;
                    if(object.contains("quitType"))
                    {
                        //告知下位机训练完成
                        sendCmdToSlave(NORMAL_STOP_E);

                        m_quitType = object.value("quitType").toInt();
                        //正常退出
                        if(1 == m_quitType)
                        {
                            emit signalGameState(e_TrainMode,GameEnd_E);
                            if(object.contains("totalTime"))
                                st_TrainReport.trainTime = object.value("totalTime").toInt();
                            if(object.contains("totalScore"))
                                st_TrainReport.score = object.value("totalScore").toInt();
                        }
                        else
                        {
                            emit signalGameState(e_TrainMode,GameEnd_E);
                            if(object.contains("totalTime"))
                                st_TrainReport.trainTime = object.value("totalTime").toInt();
                            if(object.contains("totalScore"))
                                st_TrainReport.score = object.value("totalScore").toInt();
                             qDebug()<<"游戏结束成功";
                        }
                        //生成训练报告
                        createTrainReport();
                    }
                }
                    break;
                }
            }
        }
    }
    else
    {

        //        logger()->debug(jsonError.errorString());
        //此处不该在此处停止心跳
    }
}

void GameControl::createTrainReport()
{
    m_trainingReport->setReportData(st_TrainReport,1,pointList);
    m_trainingReport->show();
}

void GameControl::sendStopCmd()
{
    QJsonObject object;
    object.insert("msgID",4);
    QJsonDocument document;
    document.setObject(object);
    QByteArray sendArray = document.toJson();
    QString ip("127.0.0.1");
    int16_t port = 2000;
    for(int i = 0;i < 5;i++)
    {
        m_gameSocket->writeDatagram(sendArray,QHostAddress(ip),port);
        Sleep(100);
    }

    sendCmdToSlave(UNNORMAL_STOP_E);

}

void GameControl::sendCmdToSlave(E_SLAVECMD cmd,int angleX,int angleY,int time)
{
    int sum =0;
    QByteArray datagram(11,0);
    datagram[0]=0x55;
    datagram[1]=(uint8_t)cmd;

    switch(cmd)
    {
    case START_CMD_E:
    {
        datagram[2] = m_st_gameParam.gameTime;
        datagram[3] = m_st_gameParam.resistance;
        datagram[4] = m_st_gameParam.maxAngle;
        datagram[5] = m_st_gameParam.trainDifficulty + 1;
        if(m_st_gameParam.gameplay == tr("随机"))
            datagram[6] = 1;
        else if(m_st_gameParam.gameplay == tr("定向"))
            datagram[6] = 2;
        datagram[7] = m_st_gameParam.direction;
        datagram[8] = m_st_gameParam.game+1;
//        m_sendTimer->start();

    }
        break;
    case NORMAL_STOP_E:
    case UNNORMAL_STOP_E:
    {
        datagram[2] = m_st_gameParam.gameTime;
        datagram[3] = m_st_gameParam.resistance;
        datagram[4] = m_st_gameParam.maxAngle;
        datagram[5] = m_st_gameParam.trainDifficulty + 1;
        if(m_st_gameParam.gameplay == tr("随机"))
            datagram[6] = 1;
        else if(m_st_gameParam.gameplay == tr("定向"))
            datagram[6] = 2;
        datagram[7] = m_st_gameParam.direction;
        datagram[8] = m_st_gameParam.game+1;
//        m_sendTimer->stop();
    }
        break;
    case REAL_PARAM_E:
    {
        datagram[2] = time;
        datagram[3] = angleY + 12;
        datagram[4] = angleX + 12;
    }
        break;
    }

    for(int i = 0;i <10;i++)
        sum += datagram[i];

    datagram[10]=sum%255;

//    qDebug()<<datagram.toHex();
    sender->writeDatagram(datagram.data(), datagram.size(),
                              QHostAddress("192.168.1.120"), 6666);
}

void GameControl::sendCurrentPointToGame(QPoint point)
{

    QJsonObject Xobject;
    Xobject.insert("current",point.x());
    Xobject.insert("min",0);

    QJsonObject Yobject;
    Yobject.insert("current",point.y());
    Yobject.insert("min",0);

    QJsonObject object;
    object.insert("msgID",2);
    object.insert("TypeID",1);
    object.insert("m_xv",Xobject);
    object.insert("m_yv",Yobject);
    QJsonDocument document;
    document.setObject(object);
    QByteArray sendArray = document.toJson();
    QString ip("127.0.0.1");
    int16_t port = 2000;
    m_gameSocket->writeDatagram(sendArray,QHostAddress(ip),port);
}

//给游戏发送当前角度
void GameControl::sendCurrentAngleToGame(float xValue,float yValue)
{
    currentXAngle = xValue;
    currentYAngle = yValue;

    static float lastX = 0,lastY = 0;
    if(!(qAbs(lastX-xValue) < 0.1 && qAbs(lastY - yValue) < 0.1))
    {
        pointList.append(QPointF(xValue,yValue));
        lastX = xValue;
        lastY = yValue;
    }

    QJsonObject Xobject;
    Xobject.insert("current",xValue);
    Xobject.insert("min",-m_maxAngle);
    Xobject.insert("max",m_maxAngle);

    QJsonObject Yobject;

    Yobject.insert("current",yValue);
    Yobject.insert("min",-m_maxAngle);
    Yobject.insert("max",m_maxAngle);

    QJsonObject Zobject;
    Zobject.insert("current",0);
    Zobject.insert("min",0);
    Zobject.insert("max",0);

    QJsonObject Wobject;
    Wobject.insert("current",0);
    Wobject.insert("min",0);
    Wobject.insert("max",0);

    QJsonObject Robject;
    Robject.insert("current",0);
    Robject.insert("min",0);
    Robject.insert("max",0);

    QJsonObject object;
    object.insert("m_xv",Xobject);
    object.insert("m_yv",Yobject);
    object.insert("m_zv",Zobject);
    object.insert("m_wv",Wobject);
    object.insert("m_rv",Robject);
    QJsonDocument document;
    document.setObject(object);
    QByteArray sendArray = document.toJson();

    QString ip("127.0.0.1");
    int16_t port = 2000;
    m_gameSocket->writeDatagram(sendArray,QHostAddress(ip),port);

}


//游戏界面关闭时间
void GameControl::slotWaitTimer()
{
    //关闭等待界面
    m_waitingDialog->setDialogCloseState(true);
}

void GameControl::slotSendRealParam()
{
    int durationTime = st_TrainReport.reportDate.secsTo(QDateTime::currentDateTime())/60;

    sendCmdToSlave(REAL_PARAM_E,currentXAngle,currentYAngle,durationTime);
}


